package com.yixun.util;

import com.yixun.controller.BaseController;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Random;

public class LoginValidateImg {

    private static String randomCodeKey = "RANDOM_CODE_KEY";
    private static boolean caseInsensitive = true;
    private int img_width = 62;
    private int img_height = 22;

    public LoginValidateImg(){}

    public LoginValidateImg(int width, int height, boolean isCaseInsensitive) {
        if(width <=0 || height <=0)
        {
            throw new IllegalArgumentException("Image width or height or count must be > 0");
        }
        this.img_width = width;
        this.img_height = height;
        caseInsensitive = isCaseInsensitive;
    }

    public void getValidateImg(HttpServletResponse response){
        ServletOutputStream sos = null;
        try {
            sos = response.getOutputStream();
            BufferedImage image = new BufferedImage(img_width, img_height, BufferedImage.TYPE_INT_RGB);
            String vCode = drawGraphic(image);
            vCode = encrypt(vCode);
            Cookie cookie = new Cookie(randomCodeKey, vCode);
            cookie.setMaxAge(-1);
            cookie.setPath("/");
            response.addCookie(cookie);
            response.setHeader("Pragma","no-cache");
            response.setHeader("Cache-Control","no-cache");
            response.setDateHeader("Expires", 0);
            response.setContentType("image/jpeg");

            ImageIO.write(image, "jpeg",sos);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (null != sos) {
                try {
                    sos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    private String drawGraphic(BufferedImage image) throws Exception {
        // 获取图形上下文
        Graphics g = image.createGraphics();

        // 设定图像背景色(因为是做背景，所以偏淡)
        g.setColor(getRandColor(180, 250));
        g.fillRect(0, 0, img_width, img_height);
        // 设置字体
        g.setFont(new Font("Times New Roman", Font.PLAIN, 17));

        String rstr = "";
        RandomStrg rst = new RandomStrg();
        rst.setCharset("0-9");
        rst.setLength("2");
        rst.generateRandomObject();
        rstr = rst.getRandom();

        // 取随机产生的认证码(2位数字)
        String sRand = "";
        sRand = rstr;
        String rand = "";
        int count = 0;
        for (int i = 0; i < sRand.length(); i++) {
            count += Integer.parseInt(String.valueOf(rstr.charAt(i)));
            rand += String.valueOf(rstr.charAt(i));
            if (i == 0) {
                rand += "+";
            }

            // 生成随机颜色(因为是做前景，所以偏深)
            g.setColor(getRandColor(10, 150));

            // 将此字画到图片上
            // g.drawString(str.toString(), 4, 17);
        }
        rand = rand+"=?";
        g.drawString(rand, 8, 17);

        // 图象生效
        g.dispose();
        return count+"";
    }

    private Color getRandColor(int fc, int bc){
        Random random = new Random();
        if (fc > 255)
            fc = 255;
        if (bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

    private static String encrypt(String srcStr){
        try {
            String result = "";
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] bytes = md.digest(srcStr.getBytes(StandardCharsets.UTF_8));
            for (byte b:bytes) {
                String hex = Integer.toHexString(b & 0xFF).toUpperCase();
                result += ((hex.length() == 1 ) ? "0" : "") + hex;
            }
            return result;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static boolean validate(String inputRandomCode, BaseController controller){
        if (caseInsensitive) {
            inputRandomCode = inputRandomCode.toUpperCase();
        }
        inputRandomCode = encrypt(inputRandomCode);
        return inputRandomCode.equals(controller.getCookie(randomCodeKey));
    }
}
